﻿using System;
using System.Collections;
using System.Collections.Specialized;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Windows.Media;

namespace Gmantis.Controls.Toolbar
{
    [ContentProperty("ToolbarItems")]
    public class Toolbar : System.Windows.Controls.ItemsControl
    {
        // Fields
        public static readonly DependencyProperty FocusBrushProperty = DependencyProperty.Register("FocusBrush", typeof(Brush), typeof(Toolbar), null);
        private bool insync;
        private static readonly DependencyProperty ItemsInternalProperty = DependencyProperty.Register("ItemsInternal", typeof(System.Collections.ObjectModel.ObservableCollection<object>), typeof(Toolbar), new PropertyMetadata(null));
        private ItemsPresenter itemsPresenter;
        public static readonly DependencyProperty MouseOverBrushProperty = DependencyProperty.Register("MouseOverBrush", typeof(Brush), typeof(Toolbar), null);
        public static readonly DependencyProperty PressedBrushProperty = DependencyProperty.Register("PressedBrush", typeof(Brush), typeof(Toolbar), null);
        public static readonly DependencyProperty ShowCollapseButtonProperty = DependencyProperty.Register("ShowCollapseButton", typeof(bool), typeof(Toolbar), new PropertyMetadata(false, new PropertyChangedCallback(Toolbar.OnShowCollapseButtonPropertyChanged)));
        public static readonly DependencyProperty ShowHelpButtonProperty = DependencyProperty.Register("ShowHelpButton", typeof(bool), typeof(Toolbar), new PropertyMetadata(false, new PropertyChangedCallback(Toolbar.OnShowHelpButtonPropertyChanged)));
        private ToolbarTabControl tabControl;
        public static readonly DependencyProperty TabItemsSourceProperty = DependencyProperty.Register("ToolbarItemsSource", typeof(IEnumerable), typeof(Toolbar), new PropertyMetadata(null, new PropertyChangedCallback(Toolbar.OnToolbarItemsSourceChanged)));
        public static readonly DependencyProperty ToolbarGroupStyleProperty = DependencyProperty.Register("ToolbarGroupStyle", typeof(Style), typeof(Toolbar), new PropertyMetadata(new PropertyChangedCallback(Toolbar.OnToolbarGroupStylePropertyChanged)));
        public static readonly DependencyProperty ToolbarTabStyleProperty = DependencyProperty.Register("ToolbarTabStyle", typeof(Style), typeof(Toolbar), new PropertyMetadata(new PropertyChangedCallback(Toolbar.OnToolbarTabStylePropertyChanged)));

        // Events
        public event EventHandler HelpClick;

        // Methods
        public Toolbar()
        {
            base.DefaultStyleKey = typeof(Toolbar);
            this.SetCustomDefaultValues();
        }

        private void Items_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            this.SyncItems();
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            this.tabControl = base.GetTemplateChild("tabControl") as ToolbarTabControl;
            if (this.tabControl != null)
            {
                this.tabControl.Toolbar = this;
                if ((this.tabControl.ReadLocalValue(FrameworkElement.StyleProperty) == DependencyProperty.UnsetValue) && (this.ToolbarTabStyle != null))
                {
                    this.tabControl.Style = this.ToolbarTabStyle;
                }
                this.tabControl.SetBinding<Toolbar>(Control.ForegroundProperty, this, tb => tb.Foreground);
            }
            this.itemsPresenter = base.GetTemplateChild("itemsPresenter") as ItemsPresenter;
            this.SyncItems();
        }

        internal void OnHelpClick()
        {
            if (this.HelpClick != null)
            {
                this.HelpClick(this, EventArgs.Empty);
            }
        }

        private void OnShowCollapseButtonChanged(bool oldValue)
        {
            if ((this.tabControl != null) && (this.tabControl._elementCollapseButton != null))
            {
                this.tabControl._elementCollapseButton.Visibility = this.ShowCollapseButton ? Visibility.Visible : Visibility.Collapsed;
            }
        }

        private static void OnShowCollapseButtonPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Toolbar toolbar = d as Toolbar;
            bool oldValue = (bool)e.OldValue;
            toolbar.OnShowCollapseButtonChanged(oldValue);
        }

        private void OnShowHelpButtonChanged(bool oldValue)
        {
            if ((this.tabControl != null) && (this.tabControl._elementHelpButton != null))
            {
                this.tabControl._elementHelpButton.Visibility = this.ShowHelpButton ? Visibility.Visible : Visibility.Collapsed;
            }
        }

        private static void OnShowHelpButtonPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Toolbar toolbar = d as Toolbar;
            bool oldValue = (bool)e.OldValue;
            toolbar.OnShowHelpButtonChanged(oldValue);
        }

        private void OnToolbarGroupStyleChanged(Style oldValue)
        {
            if (this.tabControl != null)
            {
                int count = this.tabControl.Items.Count;
                for (int i = 0; i < count; i++)
                {
                    ToolbarTabItem item = this.tabControl.Items[i] as ToolbarTabItem;
                    if (item != null)
                    {
                        foreach (ToolbarGroup group in item.Groups)
                        {
                            if (group.Style == oldValue)
                            {
                                group.Style = this.ToolbarGroupStyle;
                            }
                        }
                    }
                }
            }
        }

        private static void OnToolbarGroupStylePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Toolbar toolbar = d as Toolbar;
            Style oldValue = (Style)e.OldValue;
            toolbar.OnToolbarGroupStyleChanged(oldValue);
        }

        private static void OnToolbarItemsSourceChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            ((Toolbar)obj).SyncItems();
        }

        private void OnToolbarTabStyleChanged(Style oldValue)
        {
            if ((this.tabControl != null) && (this.tabControl.Style == oldValue))
            {
                this.tabControl.Style = this.ToolbarTabStyle;
            }
        }

        private static void OnToolbarTabStylePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Toolbar toolbar = d as Toolbar;
            Style oldValue = (Style)e.OldValue;
            toolbar.OnToolbarTabStyleChanged(oldValue);
        }

        protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
        {
            base.PrepareContainerForItemOverride(element, item);
            FrameworkElement target = element as ToolbarGroup;
            if (target != null)
            {
                target.SetBinding<Toolbar>(Control.FontFamilyProperty, this, tb => tb.FontFamily);
                target.SetBinding<Toolbar>(Control.FontSizeProperty, this, tb => tb.FontSize);
                target.SetBinding<Toolbar>(Control.FontStretchProperty, this, tb => tb.FontStretch);
                target.SetBinding<Toolbar>(Control.FontStyleProperty, this, tb => tb.FontStyle);
                target.SetBinding<Toolbar>(Control.FontWeightProperty, this, tb => tb.FontWeight);
                target.SetBinding<Toolbar>(Control.ForegroundProperty, this, tb => tb.Foreground);
                target.SetBinding<Toolbar>(Control.BackgroundProperty, this, tb => tb.Background);
                target.SetBinding<Toolbar>(Control.BorderBrushProperty, this, tb => tb.BorderBrush);
                target.SetBinding<Toolbar>(ToolbarGroup.PressedBrushProperty, this, tb => tb.PressedBrush);
                target.SetBinding<Toolbar>(ToolbarGroup.MouseOverBrushProperty, this, tb => tb.MouseOverBrush);
                target.SetBinding<Toolbar>(ToolbarGroup.FocusBrushProperty, this, tb => tb.FocusBrush);
            }
        }

        private void SetCustomDefaultValues()
        {
            base.SetValue(ItemsInternalProperty, new System.Collections.ObjectModel.ObservableCollection<object>());
            this.ToolbarItems.CollectionChanged += new NotifyCollectionChangedEventHandler(this.Items_CollectionChanged);
        }

        private void SyncItems()
        {
            if (!this.insync)
            {
                this.insync = true;
                if (this.ToolbarItemsSource != null)
                {
                    this.ToolbarItems.Clear();
                    foreach (object obj2 in this.ToolbarItemsSource)
                    {
                        ToolbarTabItem item = new ToolbarTabItem
                        {
                            DataContext = obj2
                        };
                        this.ToolbarItems.Add(item);
                    }
                }
                if ((this.tabControl != null) && (this.itemsPresenter != null))
                {
                    this.tabControl.Items.Clear();
                    base.Items.Clear();
                    bool flag = false;
                    foreach (object obj3 in this.ToolbarItems)
                    {
                        if (obj3 is TabItem)
                        {
                            flag = true;
                            TabItem target = (TabItem)obj3;
                            target.SetBinding<Toolbar>(Control.FontFamilyProperty, this, tb => tb.FontFamily);
                            target.SetBinding<Toolbar>(Control.FontSizeProperty, this, tb => tb.FontSize);
                            target.SetBinding<Toolbar>(Control.FontStretchProperty, this, tb => tb.FontStretch);
                            target.SetBinding<Toolbar>(Control.FontStyleProperty, this, tb => tb.FontStyle);
                            target.SetBinding<Toolbar>(Control.FontWeightProperty, this, tb => tb.FontWeight);
                            target.SetBinding<Toolbar>(Control.BackgroundProperty, this, tb => tb.Background);
                            target.SetBinding<Toolbar>(Control.BorderBrushProperty, this, tb => tb.BorderBrush);
                            target.SetBinding<Toolbar>(TabItem.PressedBrushProperty, this, tb => tb.PressedBrush);
                            target.SetBinding<Toolbar>(TabItem.MouseOverBrushProperty, this, tb => tb.MouseOverBrush);
                            if (target.Parent != this.tabControl)
                            {
                                TabControl parent = target.Parent as TabControl;
                                if (parent != null)
                                {
                                    parent.Items.Remove(target);
                                }
                            }
                            if (!this.tabControl.Items.Contains(target))
                            {
                                this.tabControl.Items.Add(target);
                            }
                        }
                        else
                        {
                            base.Items.Add(obj3);
                        }
                    }
                    if (flag)
                    {
                        this.tabControl.Visibility = Visibility.Visible;
                        this.itemsPresenter.Visibility = Visibility.Collapsed;
                    }
                    else
                    {
                        this.tabControl.Visibility = Visibility.Collapsed;
                        this.itemsPresenter.Visibility = Visibility.Visible;
                    }
                }
                else
                {
                    base.Items.Clear();
                    foreach (object obj4 in this.ToolbarItems)
                    {
                        base.Items.Add(obj4);
                    }
                }
                this.insync = false;
            }
        }

        // Properties
        public Brush FocusBrush
        {
            get { return (Brush)GetValue(FocusBrushProperty); }
            set { SetValue(FocusBrushProperty, value); }
        }

        public Brush MouseOverBrush
        {
            get { return (Brush)GetValue(MouseOverBrushProperty); }
            set { SetValue(MouseOverBrushProperty, value); }
        }

        public Brush PressedBrush
        {
            get { return (Brush)GetValue(PressedBrushProperty); }
            set { SetValue(PressedBrushProperty, value); }
        }

        public bool ShowCollapseButton
        {
            get { return (bool)GetValue(ShowCollapseButtonProperty); }
            set { SetValue(ShowCollapseButtonProperty, value); }
        }

        public bool ShowHelpButton
        {
            get { return (bool)GetValue(ShowHelpButtonProperty); }
            set { SetValue(ShowHelpButtonProperty, value); }
        }

        public Style ToolbarGroupStyle
        {
            get { return (Style)GetValue(ToolbarGroupStyleProperty); }
            set { SetValue(ToolbarGroupStyleProperty, value); }
        }

        public System.Collections.ObjectModel.ObservableCollection<object> ToolbarItems
        {
            get { return (System.Collections.ObjectModel.ObservableCollection<object>)GetValue(ItemsInternalProperty); }
        }

        public IEnumerable ToolbarItemsSource
        {
            get { return (IEnumerable)GetValue(TabItemsSourceProperty); }
            set { SetValue(TabItemsSourceProperty, value); }
        }

        public Style ToolbarTabStyle
        {
            get { return (Style)GetValue(ToolbarTabStyleProperty); }
            set { SetValue(ToolbarTabStyleProperty, value); }
        }
    }
}
